home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / client / msg / callServer.c next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  7.0 KB  |  303 lines

  1. /*
  2.  *   $RCSfile: callServer.c,v $  
  3.  *   $Revision: 1.2 $  
  4.  *   $Date: 1996/05/04 23:51:44 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38.  
  39. #include "sysdefs.h"
  40. #include "ess.h"
  41. #include "checking.h"
  42. #include "trace.h"
  43. #include "error.h"
  44. #include "list.h"
  45. #include "tid.h"
  46. #include "io.h"
  47. #include "lock.h"
  48. #include "object.h"
  49. #include "msgdefs.h"
  50. #include "trans.h"
  51. #include "bf.h"
  52. #include "lsn.h"
  53. #include "loginfo.h"
  54. #include "serverinfo.h"
  55. #include "bitvec.h"
  56. #include "link.h"
  57. #include "msg_funcs.h"
  58. #include "trans_funcs.h"
  59. #include "msg_globals.h"
  60. #include "trans_globals.h"
  61. #include "sm_globals.h"
  62. #include "util_funcs.h"
  63. #include "trans_globals.h"
  64.  
  65.  
  66.  int
  67. callServerMulti (
  68.     SERVERINFO    *serverInfo,
  69.     IOVECENT    *_iovec,
  70.     int            veclen
  71. )
  72. {
  73.     MESSAGE *message;
  74.     TID        tidOfMessage;
  75.     int        messageType;
  76.     int        bytesSent;
  77.     int        bytesToSend = 0;
  78.  
  79.     SM_ASSERT(LEVEL_1, veclen > 0);
  80.     SM_ASSERT(LEVEL_1, _iovec != NULL);
  81.     SM_ASSERT(LEVEL_1, _iovec[0].iov_len == sizeof(MESSAGE));
  82.  
  83.     message = (MESSAGE *) _iovec[0].iov_base;
  84.  
  85.     SM_ASSERT(LEVEL_1, message != NULL);
  86.  
  87.     tidOfMessage = message->header.params.in.tid;
  88.     messageType = message->header.type;
  89.  
  90.     TRPRINT(TR_MSG, TR_LEVEL_1, ("Msg %d(tid=%d)-->%s,%s ", 
  91.         messageType, tidOfMessage, 
  92.         serverInfo->hostName, serverInfo->name));
  93.  
  94.     if ( !(serverInfo->flags & SERV_CONNECTED) ) {
  95.         SM_ERROR(TYPE_USER, esmSERVERDIED);
  96.         return(esmFAILURE);
  97.     }
  98.  
  99.     /*
  100.      *    put the magic (version) number  in the message
  101.      *    see if a repsonse is expected or not 
  102.      */
  103.     message->header.version = MESSAGE_VERSION;
  104.  
  105.     /*
  106.      *    Keep trying to send the message is the write is interrupted
  107.      */
  108.     while (TRUE) {
  109.  
  110.         /*
  111.          *    See if there is extra data (i.e. a page) to send with the message
  112.          */
  113. #ifdef DEBUG
  114.         if (veclen > 0) {
  115.             int i;
  116.  
  117.             for(i=0; i<veclen; i++) {
  118.                 SM_ASSERT(LEVEL_1, _iovec[i].iov_len != 0);
  119.                 SM_ASSERT(LEVEL_1, _iovec[i].iov_base != NULL);
  120.             }
  121.             SM_ASSERT(LEVEL_1, _iovec != NULL);
  122.         } else {
  123.             SM_ASSERT(LEVEL_1, _iovec == NULL);
  124.         }
  125. #endif DEBUG
  126.         SM_ASSERT(LEVEL_1, _iovec[0].iov_len == sizeof(MESSAGE));
  127.  
  128.         {
  129.             int i;
  130.             for(bytesToSend = 0, i=0; i<veclen; i++) {
  131.                 bytesToSend +=  _iovec[i].iov_len;
  132.             }
  133.         }
  134.  
  135. #if !(defined(linux))
  136.         if (veclen > 1 ) {
  137.             bytesSent = writev(serverInfo->socket, _iovec, veclen);
  138.         } else {
  139.             /* ever so slightly cheaper */
  140.             bytesSent = 
  141.                 write(serverInfo->socket, (char *) message, sizeof(MESSAGE));
  142.         }
  143. #else
  144. /*
  145.   We can't seem to consistently send large chunks of data to a socket
  146.   using the writev() function.  So, at the cost of efficiency, we'll
  147.   send each buffer separately.  We'll also check to see if only a partial
  148.   write occurred, then send the remainder.
  149. */
  150.         if (veclen > 1 ) {
  151.             char *msg_base;
  152.             int i, nSent, nSend, nThisTime;
  153.             bytesSent = 0;
  154.             for(i=0; i<veclen; i++) {
  155.                 nSend = _iovec[i].iov_len;
  156.                 nSent = 0;
  157.                 msg_base = (char *)_iovec[i].iov_base;
  158.  
  159.                 while(nSend){
  160.                     nThisTime = write(serverInfo->socket,
  161.                       msg_base, nSend);
  162.                     TRPRINT(TR_MSG, TR_LEVEL_2,
  163.                     ("Buffer %d: sent %d of %d bytes",
  164.                     i, nThisTime, nSend));
  165.                     nSent += nThisTime;
  166.                     msg_base += nThisTime;
  167.                     nSend -= nThisTime;
  168.                 }
  169.                 bytesSent += nSent;
  170.             }
  171.         } else {
  172.             char *msg_base;
  173.             int nSend, nThisTime;
  174.             bytesSent = 0;
  175.             nSend = sizeof(MESSAGE);
  176.             msg_base = (char *)message;
  177.             while(nSend){
  178.                 nThisTime = write(serverInfo->socket,
  179.                           msg_base, nSend);
  180.                 TRPRINT(TR_MSG, TR_LEVEL_2,
  181.                 ("Write: sent %d of %d bytes",
  182.                 nThisTime, nSend));
  183.                 bytesSent += nThisTime;
  184.                 msg_base += nThisTime;
  185.                 nSend -= nThisTime;
  186.             }
  187.         }
  188. #endif !linux
  189.  
  190.         /*
  191.          *    See if the call was interrupted
  192.          */
  193.         if ((bytesSent < 0) && (errno == EINTR)) {
  194.             SM_ERROR(TYPE_LOG, errno);
  195.             continue; /* try again */
  196.         }
  197.         break; /* finished or error */
  198.     }
  199.  
  200.     /*
  201.      *    If the write failed, abort the transaction
  202.      */
  203.     if (bytesSent < 0) {
  204.  
  205.         SM_ERROR(TYPE_SYS, errno);
  206.  
  207.         switch(errno) {
  208.         case ENETDOWN:
  209.         case ENETUNREACH:
  210.         case ENETRESET:
  211.         case ECONNABORTED:
  212.         case ECONNRESET:
  213.         case EPIPE:
  214.  
  215.             (void) detectedDisconnect(serverInfo);
  216.             break;
  217.  
  218.         case EINTR:
  219.             SM_ERROR(TYPE_CRASH, esmINTERNAL);
  220.             break;
  221.     
  222.         default:
  223.  
  224.             CLIENT_ABORT_TID( getLocalTid() );
  225.             break;
  226.         }
  227.  
  228.         return(esmFAILURE);
  229.  
  230.     } else if (bytesSent != bytesToSend) {
  231.  
  232.         if (TransRec.clientTransState == T_ACTIVE) {
  233.             TransRec.clientTransState = T_ABORT;
  234.         }
  235.         SM_ERROR(TYPE_SYS, errno);
  236.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  237.         return(esmFAILURE);
  238.     }
  239.  
  240.     TRPRINT(TR_MSG, TR_LEVEL_2, ("sent %d bytes successfully", bytesSent));
  241.  
  242.     MsgStats.sent[messageType]++;
  243.     incPages(bytesSent, SENT, TRUE);
  244.  
  245.     /* 
  246.      *    see if we do not need to read the reply
  247.      */
  248.     if (message->header.replyRequested == FALSE) {
  249.         MsgStats.no_reply_requested[messageType]++;
  250.         return(esmNOERROR);
  251.     }
  252.  
  253.     /*
  254.      * Read the reply (message).  There may be data apppended
  255.      * to the message structure. They are read by the caller of this func.
  256.      */
  257.     if (msg_Receive(serverInfo, message, (int)sizeof(MESSAGE)) < 0)    {
  258.         return(esmFAILURE);
  259.     }
  260. #ifdef DEBUG
  261.     if(messageType != message->header.type) {
  262.         fprintf(stderr, "got reply for msg type %d; expected %d\n",
  263.                 message->header.type, messageType);
  264.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  265.     }
  266. #endif DEBUG
  267.  
  268.     TRPRINT(TR_MSG, TR_LEVEL_1, ("got reply for msg type %d",
  269.                 message->header.type));
  270.  
  271.     if (message->header.params.out.errno != esmNOERROR)    {
  272.         SM_ERROR(TYPE_USER, (int) message->header.params.out.errno);
  273.         return(esmFAILURE);
  274.     
  275.     } else {
  276.         return(esmNOERROR);
  277.     }
  278. }
  279.  
  280.  int
  281. callServer (
  282.     SERVERINFO    *serverInfo,
  283.     MESSAGE        *message,
  284.     char        *data,
  285.     int            dataLength
  286. )
  287. {
  288.     IOVECTOR IoVector;
  289.     int i = 1;
  290.  
  291.     IoVector[0].iov_base = (char *) message;
  292.     IoVector[0].iov_len = sizeof(MESSAGE);
  293.  
  294.     if(dataLength > 0) {
  295.         IoVector[1].iov_base = data;
  296.         IoVector[1].iov_len = dataLength;
  297.         i++;
  298.     }
  299.  
  300.     return callServerMulti(serverInfo, &(IoVector[0]), i);
  301. }
  302.  
  303.